﻿using Frame.Core.Common.Attributes;
using Frame.Core.Common.Auth;
using Frame.Core.Common.Cache;
using Frame.Core.IServices.Admin;
using Frame.Core.Models;
using Frame.Core.Models.Dto;
using Frame.Core.Repository;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Threading.Tasks;

namespace Frame.Core.Services.Admin
{
    public class UserService : BaseService<Users>, IUserService
    {
        readonly IUser _user;
        readonly ICache _cache;
        readonly IRepositoryBase<Users> _userRepository;
        readonly IRepositoryBase<Powers> _powerRepository;
        readonly IRepositoryBase<RolePowers> _rolePowerRepository;
        readonly IRepositoryBase<RoleUsers> _roleUserRepository;
        readonly IRepositoryBase<TitleUsers> _titleUserRepository;
        public UserService(IUser user, ICache cache, IRepositoryBase<Users> userRepository, IRepositoryBase<Powers> powerRepository, IRepositoryBase<RolePowers> rolePowerRepository, 
            IRepositoryBase<RoleUsers> roleUserRepository,IRepositoryBase<TitleUsers> titleUserRepository)
        {
            _user = user;
            _cache = cache;
            this._userRepository = userRepository;
            base.BaseDal = userRepository;
            _powerRepository = powerRepository;
            _rolePowerRepository = rolePowerRepository;
            _roleUserRepository = roleUserRepository;
            _titleUserRepository = titleUserRepository;
        }

        public async Task<List<UsersDto>> GetUserList(PagingInfoViewModel<Users> pagingInfo, Expression<Func<Users, bool>> whereExpression)
        {
            //设置查询条件
            var list = await _userRepository.Select.OrderByPropertyNameIf(pagingInfo.SortField != null, pagingInfo.SortField, pagingInfo.Descending).OrderBy(pagingInfo.PageKey)
                .WhereIf(whereExpression!=null, whereExpression)
                .Count(out var total)
                .Page(pagingInfo.PageIndex, pagingInfo.PageSize)
                .ToListAsync<UsersDto>();
            pagingInfo.Count = total;
            return list;
        }

        public async Task<Users> GetUserFirst(Expression<Func<Users, bool>> whereExpression)
        {
            //设置查询条件
            return await _userRepository.Select
                .WhereIf(whereExpression != null, whereExpression)
                .Include(a => a.Depts)
                .ToOneAsync();
        }

        public async Task<List<string>> GetPermissionsAsync()
        {
            var key = $"dianqi_UserPowerList_{_user.Id}";
            // 将用户拥有的权限列表保存在Session中，这样就避免每个请求多次查询数据库
            if (!await _cache.ExistsAsync(key))
            {

                List<string> rolePowerNames = new List<string>();

                // 超级管理员拥有所有权限
                if (_user.Name == "admin")
                {
                    rolePowerNames = await _powerRepository.Select.ToListAsync(a=>a.Name);

                }
                else
                {
                    List<int> roleIDs = await GetIdentityRoleIDs(_user.Name);
                    rolePowerNames = await _rolePowerRepository.Select.Where(a=>a.PowerID==a.Powers.ID && roleIDs.Contains(a.RoleID)).Distinct().ToListAsync(a => a.Powers.Name);
                }
                await _cache.SetAsync(key, rolePowerNames);
            }
            return _cache.Get<List<string>>(key);
        }
        /// <summary>
        /// 当前登录用户的角色列表
        /// </summary>
        /// <returns></returns>
        public async Task<List<int>> GetIdentityRoleIDs(string userName)
        {
            List<int> listRoleID = new List<int>();
            if (!string.IsNullOrEmpty(userName))
            {
                listRoleID = await _roleUserRepository.Select.Where(a => _userRepository.Select.As("b").Where(b=>b.Name==userName).ToList(b=>b.ID).Equals(a.UserID)).ToListAsync(a => a.RoleID);
            }

            return listRoleID;
        }

        [Transaction]
        public async Task AddUserAsync(Users user,int[] arrRoles,int[] arrTitles)
        {

            // 插入用户
            await _userRepository.AddAsync(user);
            var roleUserList = arrRoles.Select(u => new RoleUsers { UserID = user.ID, RoleID = u }).ToArray();
            await _roleUserRepository.AddAsync(roleUserList);

            var titleUserList = arrTitles.Select(u => new TitleUsers { UserID = user.ID, TitleID = u }).ToArray();
            await _titleUserRepository.AddAsync(titleUserList);
        }

        [Transaction]
        public async Task EditUserAsync(Users user, int[] arrRoles, int[] arrTitles)
        {
            // 更新用户
            var oldUser = await _userRepository.GetAsync(s=>s.ID==user.ID);

            //不更新的列，复制给修改的对象
            user.Password = oldUser.Password;
            user.CreateTime= oldUser.CreateTime;
            user.Name = oldUser.Name;
            await AttachEditAsync(oldUser, user);

            await _roleUserRepository.DelAsync(d => d.UserID == user.ID);
            var roleUserList = arrRoles.Select(u => new RoleUsers { UserID = user.ID, RoleID = u }).ToArray();
            await _roleUserRepository.AddAsync(roleUserList);

            await _titleUserRepository.DelAsync(d => d.UserID == user.ID);
            var titleUserList = arrTitles.Select(u => new TitleUsers { UserID = user.ID, TitleID = u }).ToArray();
            await _titleUserRepository.AddAsync(titleUserList);
        }
    }
}
